package core;

public class GridDecision extends BaseDecision {

	private static final float m_level_gap = 0.015f; // level gap in percentage

	private static final float m_min_quantity = 20f;

	private static final float m_max_quantity = 50.0f;

	private static final float m_power = 1.5f;

	private static final float m_buy_level_threshold = 1f;

	private static final float m_sell_level_threshold = 1.5f;

	private static final boolean m_allow_sellfirst = false; // �Ƿ���������

	private float m_ref_price = -1;

	private float m_last_level;

	private float m_last_quantity;

	private int m_last_process;

	public GridDecision(PersonAccount account) {
		super(account);
		m_ref_price = -1;
		m_last_level = 0;
		m_last_quantity = 0;
		m_last_process = 0;
	}

	@Override
	protected boolean JudgeSell() {
		boolean ret = false;

		if (m_ref_price < 0) {
			m_ref_price = m_sell_price;
		}

		float cur_level = calLevel(m_sell_price, false);
		if (cur_level > (m_last_level + 1.5f)) {
			// should sell
			if (sell()) {
				System.out.println("cur_level: " + cur_level + " last_level: " + m_last_level
								+ "\r\n");
				m_last_level = cur_level;

				if (m_account.getGoodsQuantity() < 0.0001f) {
					m_ref_price = m_sell_price;
				}

			}
		}

		return ret;
	}

	@Override
	protected boolean JudgeBuy() {
		boolean ret = false;

		if (m_ref_price < 0) {
			m_ref_price = m_buy_price;
		}

		float cur_level = calLevel(m_buy_price, true);
		if (cur_level < (m_last_level - 1f)) {
			// should buy
			if (buy()) {
				System.out.println("cur_level: " + cur_level + " last_level: " + m_last_level
								+ "\r\n");
				m_last_level = cur_level;

				if (m_account.getGoodsQuantity() < 0.0001f) {
					m_ref_price = m_buy_price;
				}
			}
		}

		return ret;
	}

	private boolean sell() {
		boolean ret = false;

		float quantity = m_min_quantity * m_sell_level_threshold / m_buy_level_threshold;
		if (m_last_process < 0) {
			quantity = (float) Math.ceil(m_last_quantity * m_power);
			if (quantity > m_max_quantity * m_sell_level_threshold / m_buy_level_threshold) {
				quantity = m_max_quantity * m_sell_level_threshold / m_buy_level_threshold;
			}
		}

		if (!m_allow_sellfirst) {
			if (quantity > m_account.getGoodsQuantity()) {
				quantity = m_account.getGoodsQuantity();
			}
		}

		if (quantity > m_min_quantity / 2) {
			ret = m_account.sell(quantity);

			if (!ret) {
				// System.err.println(m_account.toAllResults());
				// System.err
				// .println("Failed to SELL " + quantity + " goods at " +
				// GoldDataRead.printDate(m_current_time));
			} else {
				m_last_quantity = quantity;
				System.out.println("SELL at " + m_current_time);
				System.out.println("Reference price: " + m_ref_price);
			}

			m_last_process = -1;
		}

		return ret;
	}

	private boolean buy() {
		boolean ret = false;

		float quantity = m_min_quantity;
		if (m_last_process > 0) {
			quantity = (float) Math.ceil(m_last_quantity * m_power);
			if (quantity > m_max_quantity) {
				quantity = m_max_quantity;
			}
		}

		ret = m_account.buy(quantity);
		if (!ret) {
			// System.err.println(m_account.toAllResults());
			// System.err.println("Failed to BUY " + quantity + " goods at " +
			// GoldDataRead.printDate(m_current_time));
		} else {
			m_last_quantity = quantity;
			System.out.println("BUY at " + m_current_time);
			System.out.println("Reference price: " + m_ref_price);
		}

		m_last_process = 1;

		return ret;
	}

	private float calLevel(float price, boolean isBuy) {
		float level = 0;

		float gap = (price - m_ref_price) / m_ref_price;
		if (isBuy) {
			level = gap / m_level_gap;
		} else {
			level = gap / m_level_gap;
		}

		return level;
	}

}
